const db = require('../config/DBconnector');
const { DataTypes } = require('sequelize');
const { numberGetter, timeGetter } = require('../utils/ModelUtil');
const BusinessError = require('../exception/businessError');
const { TradeStatus } = require('../constants/DbEnum');

const name = 'Trade';

const fields = {
  buyOrderId: {
    type: DataTypes.INTEGER,
    allowNull: false,
  },
  sellOrderId: {
    type: DataTypes.INTEGER,
    allowNull: false,
  },
  buyUsername: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  sellUsername: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  baseCoinType: {
    // USD, BTC, ETH, BCH...
    type: DataTypes.STRING(10),
    allowNull: false,
  },
  counterCoinType: {
    // USD, BTC, ETH, BCH...
    type: DataTypes.STRING(10),
    allowNull: false,
  },
  price: {
    // counterCoinAmount * price = baseCoinAmount
    type: DataTypes.DECIMAL(40, 20),
    allowNull: false,
    validate: { min: 0.01 },
    get: numberGetter(),
  },
  sellDepositPrice: {
    type: DataTypes.DECIMAL(40, 20),
    allowNull: false,
    validate: { min: 0 },
    defaultValue: 0,
    get: numberGetter(),
  },
  baseCoinAmount: {
    type: DataTypes.DECIMAL(40, 20),
    allowNull: false,
    validate: { min: 0.01 },
    get: numberGetter(),
  },
  counterCoinAmount: {
    type: DataTypes.DECIMAL(40, 20),
    allowNull: false,
    validate: { min: 0.0001 },
    get: numberGetter(),
  },
  buyBaseCoinAddress: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  sellBaseCoinAddress: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  buyCounterCoinAddress: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  sellCounterCoinAddress: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  status: {
    // INIT, PENDING, EXPIRED, COMPLETED...
    type: DataTypes.STRING(12),
    allowNull: false,
    defaultValue: TradeStatus.INIT,
  },
  expiredTimestamp: {
    type: DataTypes.DATE,
    defaultValue: () => {
      return Date.now() + 60 * 60 * 1000;
    },
    get: timeGetter(),
  },

  baseCoinTx: {
    type: DataTypes.STRING,
  },
  counterCoinTx: {
    type: DataTypes.STRING,
  },
};

const getterMethods = {
  depositAmount() {
    return this.status == TradeStatus.EXPIRED ? this.sellDepositPrice * this.baseCoinAmount : 0;
  },
  finalBaseCoinAmount() {
    return this.status == TradeStatus.COMPLETED ? this.baseCoinAmount : 0;
  },
};

const validate = {
  validPriceAndAmount() {
    if (this.baseCoinAmount * this.price != this.counterCoinAmount) {
      throw new BusinessError(400, 'price and amount pair not valid!');
    }
  },
};

const model = db.define(name, fields, { validate, getterMethods });

module.exports = model;
